/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package com.plian.system.service.fr.bank.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.plian.Tools.AllDayOfMonth;
import com.plian.Tools.DateUtil;
import com.plian.Tools.TokenUtil;
import com.plian.system.dto.fr.bank.BankRecordDTO;
import com.plian.system.entity.fr.bank.BankKey;
import com.plian.system.entity.fr.bank.BankRecord;
import com.plian.system.mapper.fr.bank.BankKeyMapper;
import com.plian.system.mapper.fr.bank.BankRecordMapper;
import com.plian.system.model.CommonCode;
import com.plian.system.model.R;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.service.fr.bank.IBankRecordService;
import com.plian.system.vo.report.HeaderVO;
import com.plian.system.vo.report.ReportReturnVO;
import com.plian.system.vo.report.ReportVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.flowable.editor.language.json.converter.util.CollectionUtils;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 服务实现类
 */
@Slf4j
@Service
@AllArgsConstructor
public class BankRecordServiceImpl extends BaseServiceImpl<BankRecordMapper, BankRecord> implements IBankRecordService {

    private BankKeyMapper bankKeyMapper;

    private final Lock lock = new ReentrantLock();

    @Override
    public ReportReturnVO statistics(BankRecordDTO bankRecordDTO) throws ParseException {
        ReportVO reportVO = new ReportVO();
        reportVO
                .addHeader(HeaderVO.builder().key("topGroupName").title("集团名称").build());
        List<String> dateList = AllDayOfMonth.getDay(DateUtil.parse(DateUtil.format(bankRecordDTO.getMonth(), DateUtil.PATTERN_MONTH), DateUtil.PATTERN_MONTH));
        ArrayList<String> dayList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(dateList)) {
            for (String dateStr : dateList) {
                String[] split = dateStr.split("-");
                reportVO
                        .addHeader(HeaderVO.builder().key("time" + (Integer.parseInt(split[2]) < 10 ? split[2].replace("0", "") : split[2])).title(Integer.parseInt(split[2]) < 10 ? split[2].replace("0", "") : split[2]).build());
                dayList.add(split[2]);
            }
        }
        List<BankKey> bankKeyList = bankKeyMapper.selectList(new QueryWrapper<>());
        String topGroupId = TokenUtil.getTokenOrgId();
        if ("101a8263ca8f0bfef57c6bb2e8937adc".equals(topGroupId)) {
            if (CollectionUtils.isNotEmpty(bankKeyList)) {
                ArrayList<BankRecord> bankRecords = new ArrayList<>();
                for (BankKey bankKey : bankKeyList) {
                    HashMap<String, BankRecord> dateMap = new HashMap<>();
                    for (int i = 1; i < 32; i++) {
                        dateMap.put("time" + i, new BankRecord());
                    }
                    List<BankRecord> bankDateList = baseMapper.statistics(bankKey.getTopGroupId(), DateUtil.format(bankRecordDTO.getMonth(), DateUtil.PATTERN_MONTH));
                    BankRecord data = new BankRecord();
                    data.setTopGroupId(bankKey.getTopGroupId());
                    data.setTopGroupName(bankKey.getTopGroupName());
                    if (CollectionUtils.isNotEmpty(bankDateList)) {
                        for (BankRecord bankRecordDate : bankDateList) {
                            List<BankRecord> dayData = super.list(Wrappers.<BankRecord>lambdaQuery()
                                    .like(BankRecord::getRecordDate, DateUtil.format(bankRecordDate.getRecordDate(), DateUtil.PATTERN_DATE))
                                    .eq(BankRecord::getTopGroupId, bankKey.getTopGroupId()));
                            BankRecord bankRecord = new BankRecord();
                            if (CollectionUtils.isNotEmpty(dayData)) {
                                for (BankRecord dayDatum : dayData) {
                                    int day = Integer.parseInt(new SimpleDateFormat("dd").format(dayDatum.getRecordDate()));
                                    String str = day >= 10 ? String.valueOf(day) : String.valueOf(day).replace("0", "");
                                    bankRecord.setPushRecord("2");
                                    if (dayDatum.getCurrentCount() != null) {
                                        bankRecord.setCurrentCount(dayDatum.getCurrentCount());
                                    }
                                    if (dayDatum.getDetailCount() != null) {
                                        bankRecord.setDetailCount(dayDatum.getDetailCount());
                                    }
                                    dateMap.put("time" + str, bankRecord);
                                }
                                for (BankRecord dayDatumRecord : dayData) {
                                    if ("1".equals(dayDatumRecord.getPushRecord())) {
                                        bankRecord.setPushRecord("1");
                                        if (dayDatumRecord.getCurrentCount() != null) {
                                            bankRecord.setCurrentCount(null);
                                        }
                                        if (dayDatumRecord.getDetailCount() != null) {
                                            bankRecord.setDetailCount(null);
                                        }
                                        int day = Integer.parseInt(new SimpleDateFormat("dd").format(dayDatumRecord.getRecordDate()));
                                        String str = day >= 10 ? String.valueOf(day) : String.valueOf(day).replace("0", "");
                                        dateMap.put("time" + str, bankRecord);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    data.setDateMap(dateMap);
                    bankRecords.add(data);
                    reportVO.setData(bankRecords);
                }
            }
        } else {
            ArrayList<BankRecord> bankRecords = new ArrayList<>();
            HashMap<String, BankRecord> dateMap = new HashMap<>();
            for (int i = 1; i < 32; i++) {
                dateMap.put("time" + i, new BankRecord());
            }
            List<BankRecord> bankDateList = baseMapper.statistics(topGroupId, DateUtil.format(bankRecordDTO.getMonth(), DateUtil.PATTERN_MONTH));
            BankRecord data = new BankRecord();
            data.setTopGroupId(topGroupId);
            data.setTopGroupName(bankKeyMapper.selectOne(new LambdaQueryWrapper<BankKey>().eq(BankKey::getTopGroupId, topGroupId)).getTopGroupName());
            if (CollectionUtils.isNotEmpty(bankDateList)) {
                for (BankRecord bankRecordDate : bankDateList) {
                    List<BankRecord> dayData = super.list(Wrappers.<BankRecord>lambdaQuery()
                            .like(BankRecord::getRecordDate,  DateUtil.format(bankRecordDate.getRecordDate(), DateUtil.PATTERN_DATE))
                            .eq(BankRecord::getTopGroupId, topGroupId));
                    BankRecord bankRecord = new BankRecord();
                    if (CollectionUtils.isNotEmpty(dayData)) {
                        for (BankRecord dayDatum : dayData) {
                            int day = Integer.parseInt(new SimpleDateFormat("dd").format(dayDatum.getRecordDate()));
                            String str = day >= 10 ? String.valueOf(day) : String.valueOf(day).replace("0", "");
                            bankRecord.setPushRecord("2");
                            if (dayDatum.getCurrentCount() != null) {
                                bankRecord.setCurrentCount(dayDatum.getCurrentCount());
                            }
                            if (dayDatum.getDetailCount() != null) {
                                bankRecord.setDetailCount(dayDatum.getDetailCount());
                            }
                            dateMap.put("time" + str, bankRecord);
                        }
                        for (BankRecord dayDatumRecord : dayData) {
                            if ("1".equals(dayDatumRecord.getPushRecord())) {
                                bankRecord.setPushRecord("1");
                                if (dayDatumRecord.getCurrentCount() != null) {
                                    bankRecord.setCurrentCount(null);
                                }
                                if (dayDatumRecord.getDetailCount() != null) {
                                    bankRecord.setDetailCount(null);
                                }
                                int day = Integer.parseInt(new SimpleDateFormat("dd").format(dayDatumRecord.getRecordDate()));
                                String str = day >= 10 ? String.valueOf(day) : String.valueOf(day).replace("0", "");
                                dateMap.put("time" + str, bankRecord);
                                break;
                            }
                        }
                    }
                }
            }
            data.setDateMap(dateMap);
            bankRecords.add(data);
            reportVO.setData(bankRecords);
        }
        ReportReturnVO reportReturnVO = new ReportReturnVO();
        reportReturnVO.setGrids(reportVO);
        R<ReportReturnVO> result = new R<>(CommonCode.SUCCESS);
        result.setPageData(reportReturnVO);
        return reportReturnVO;
    }

    @Override
    public void updateCurrentCount(String topGroupId, String topGroupName,  int currentCount) {
        try {
            lock.lock();
            BankRecord oldBankRecord = baseMapper.selectOne(new LambdaQueryWrapper<BankRecord>()
                    .eq(BankRecord::getTopGroupId, topGroupId)
                    .like(BankRecord::getRecordDate, DateUtil.format(DateUtil.now(), DateUtil.PATTERN_DATE)));

            BankRecord bankRecord = BankRecord.builder().topGroupId(topGroupId)
                    .topGroupName(topGroupName).pushRecord("2").recordDate(new Date()).build();

            if (Optional.ofNullable(oldBankRecord).isPresent()) {
                bankRecord.setId(oldBankRecord.getId());
                if (Optional.ofNullable(oldBankRecord.getCurrentCount()).isPresent()) {
                    int count = Integer.parseInt(oldBankRecord.getCurrentCount()) + currentCount;
                    bankRecord.setCurrentCount(String.valueOf(count));
                } else {
                    bankRecord.setCurrentCount(String.valueOf(currentCount));
                }
            } else {
                bankRecord.setCurrentCount(String.valueOf(currentCount));
            }
            saveOrUpdate(bankRecord);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public void updateDetailCount(String topGroupId, String topGroupName, int detailCount) {
        try {
            lock.lock();
            BankRecord oldBankRecord = baseMapper.selectOne(new LambdaQueryWrapper<BankRecord>()
                    .eq(BankRecord::getTopGroupId, topGroupId)
                    .like(BankRecord::getRecordDate, DateUtil.format(DateUtil.now(), DateUtil.PATTERN_DATE)));

            BankRecord bankRecord = BankRecord.builder().topGroupId(topGroupId)
                    .topGroupName(topGroupName).pushRecord("2").recordDate(new Date()).build();

            if (Optional.ofNullable(oldBankRecord).isPresent()) {
                bankRecord.setId(oldBankRecord.getId());
                if (Optional.ofNullable(oldBankRecord.getDetailCount()).isPresent()) {
                    int count = Integer.parseInt(oldBankRecord.getDetailCount()) + detailCount;
                    bankRecord.setDetailCount(String.valueOf(count));
                } else {
                    bankRecord.setDetailCount(String.valueOf(detailCount));
                }
            } else {
                bankRecord.setDetailCount(String.valueOf(detailCount));
            }
            saveOrUpdate(bankRecord);
            } finally {
                lock.unlock();
        }
    }

}
